package com.localcache.server.handler;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.localcache.server.context.ChannelContextManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import com.distribute.common.MsgObj;
import com.distribute.common.MsgType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;

/**
 * 缓存服务处理
 *
 * @author chennengcheng
 * @date 2021-09-13 11:08
 * @remark
 */
@ChannelHandler.Sharable
public class JvmMemoryHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(JvmMemoryHandler.class);

    /**
     * 本方法用于读取客户端发送的信息
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String data = (String) msg;
        // 空字符表示心跳
        if (data.equals("")) {
            return;
        }

        MsgObj msgObj = JSONUtil.toBean(data, new TypeReference<MsgObj>() {}, true);
        if (!MsgType.VM_MEMORY_TYPE.name().equals(msgObj.getMsgType().name())){
            // 如果不属于当前业务要处理的，那么就要向下一个处理器写入，否则自己处理
            ctx.fireChannelRead(msg);
            return;
        }

        // 获取到服务端的 信息 进行处理
//        log.info("虚拟机 + 收到消息：" + data);
    }

    /**
     * 本方法用作处理异常
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 当出现异常就关闭连接
        cause.printStackTrace();
        removeChannelMap(ctx);
        ctx.close();
    }

    /**
     * 删除 map 中 ChannelHandlerContext
     * @param ctx
     */
    private void removeChannelMap(ChannelHandlerContext ctx){
        for(String key : ChannelContextManager.channelHandlerContextMap.keySet()){
            ChannelHandlerContext channelHandlerContext = ChannelContextManager.channelHandlerContextMap.get(key);
            if(Optional.ofNullable(channelHandlerContext).map(v -> v.equals(ctx)).orElse(false)){
                ChannelContextManager.channelHandlerContextMap.remove(key);
            }
        }
    }

    /**
     * 信息获取完毕后操作
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

}
